
#include <libcoco.h>
#include "coroutine.h"
#include <stdio.h>

// #include <dbg.h>
#define CROUT_MALLOC(size)	  __builtin_malloc(size)
#define CROUT_FREE(ptr, size)   __builtin_free(ptr)

typedef struct crout_int{
	// word_t   stk_size;
	void *(*routine)(void*);
	void *arg;
	struct schedule *S;
	int coid;
}crout_int_t;

static void async_worker(struct schedule * S, void *ud){
	(void )S;
	crout_int_t *cr = (crout_int_t *)ud;
	coroutine_yield(cr->S);
	// fprintf(stderr, "start \n");
	cr->routine(cr->arg);
	// cr->ret = ret;
	// fprintf(stderr, "ret \n");
}

int 	crout_create( crout_t **pco,const crout_attr_t *attr,void *(*routine)(void*),void *arg){
	void *p = CROUT_MALLOC(sizeof(crout_int_t));
	if (!p) return -1;
	crout_int_t * cr = (crout_int_t *)p;
	// cr->stk_size = attr->stack_size;
	(void )attr;
	cr->routine = routine;
	cr->arg = arg;
	cr->S = coroutine_open();
	cr->coid = coroutine_new(cr->S, async_worker, cr);
	coroutine_resume(cr->S, cr->coid);
	*pco = (crout_t *)cr;
	// fprintf(stderr, "create succ\n");
	return 0;
}

void	crout_resume( crout_t *co){
	crout_int_t *cr = (crout_int_t *)co;
	// fprintf(stderr, "try resume\n");
	coroutine_resume(cr->S, cr->coid);
}


void	crout_yield( crout_t *co ){
	crout_int_t *cr = (crout_int_t *)co;
	coroutine_yield(cr->S);
}

void	crout_release( crout_t *co ){
	crout_int_t *cr = (crout_int_t *)co;
	coroutine_close(cr->S);
	CROUT_FREE(cr, sizeof(crout_int_t));
}

void	crout_reset(crout_t * co){
	crout_int_t *cr = (crout_int_t *)co;
	coroutine_close(cr->S);
	/* 重新申请 */
	cr->S = coroutine_open();
	cr->coid = coroutine_new(cr->S, async_worker, cr);

}
